﻿using System;
using System.Collections.Generic;
using System.Linq;
using IRCPhase2Tester.Tests;

namespace IRCPhase2Tester
{
    public enum TestType
    {
        AddUser = 1,
        AddUserNoNick = 2,
        RemoveUser = 3,
        RemoveUserNoNick = 4,
        NextHopNone = 5,
        NextHopNoNick = 6,
        NextHop = 7,
        Usertable = 8,
        FullNetworkNextHop = 9,
        NodeAcknowledgement = 10,
        LSAFlooding = 11,
        MultiUsersNextHop = 12,
        NodeDownBroadcastSilence = 13,
        CorrectedLSA = 14,
        NodeDownReroute = 15
    }

    public enum TestResult
    {
        Passed,
        Failed
    }

    public class TestTypePair
    {
        public TestType TestType { get; set; }
        public Type TestClass { get; set; }
    }

    public static class TestUtility
    {
        private static List<TestTypePair> types = new List<TestTypePair>();

        static TestUtility()
        {
            Array values = Enum.GetValues(typeof(TestType));

            foreach (TestType value in values)
            {
                switch (value)
                {
                    case TestType.AddUser:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(AddUserTest)
                        });
                        break;
                    case TestType.AddUserNoNick:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(AddUserNoNick)
                        });
                        break;
                    case TestType.RemoveUser:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(RemoveUserTest)
                        });
                        break;
                    case TestType.RemoveUserNoNick:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(RemoveUserNoNick)
                        });
                        break;
                    case TestType.NextHopNoNick:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(NextHopNoNick)
                        });
                        break;
                    case TestType.NextHopNone:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(NextHopNone)
                        });
                        break;
                    case TestType.NextHop:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(NextHopTest)
                        });
                        break;
                    case TestType.FullNetworkNextHop:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(FullNetworkNextHop)
                        });
                        break;
                    case TestType.NodeAcknowledgement:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(NodeAcknowledgement)
                        });
                        break;
                    case TestType.LSAFlooding:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(LSAFlooding)
                        });
                        break;
                    case TestType.MultiUsersNextHop:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(MultipleUsersNextHop)
                        });
                        break;
                    case TestType.NodeDownBroadcastSilence:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(NodeDownBroadcastSilence)
                        });
                        break;
                    case TestType.Usertable:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(UserTable)
                        });
                        break;
                    case TestType.CorrectedLSA:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(CorrectedLSA)
                        });
                        break;
                    case TestType.NodeDownReroute:
                        types.Add(new TestTypePair()
                        {
                            TestType = value,
                            TestClass = typeof(NodeDownReroute)
                        });
                        break;
                }
            }
        }

        public static int NumOfTests
        {
            get { return Enum.GetNames(typeof(TestType)).Length; }
        }

        public static ITest GetTest(int testNumber)
        {
            TestType type;

            if (testNumber > NumOfTests)
            {
                return null;
            }

            type = (TestType)testNumber;

            return GetTest(type);
        }

        public static TestType GetTypeOfTest(ITest test)
        {
            return types.First(t => t.TestClass == test.GetType()).TestType;
        }

        public static ITest GetTest(TestType type)
        {
            Type testType = (from t in types
                            where t.TestType == type
                            select t.TestClass).First();

            if (testType == null)
                return null;

            return (ITest)Activator.CreateInstance(testType);
        }

        public static TestType[] GetArrayOfTestTypesFromIntegerArray(int[] intList)
        {
            if (intList.Length == 0)
            {
                return null;
            }

            TestType[] testTypes = new TestType[intList.Length];

            for (int i = 0; i < intList.Length; i++)
            {
                testTypes[i] = (TestType)intList[i];
            }

            return testTypes;
        }
    }
}